package app.common.utils.dingtalk;

import com.aliyun.dingtalkoauth2_1_0.Client;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponseBody;
import com.aliyun.tea.TeaException;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.gitee.feizns.dynamic.function.TryCatch;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * 钉钉新版Api认证相关接口
 * @link 钉钉文档链接 -> <a href="https://open.dingtalk.com/document/orgapp-server/obtain-the-access_token-of-an-internal-app">获取企业内部应用的accessToken</a>
 * @author feizns
 * @since 2022/11/9
 */
@Slf4j
public class Auth2Utils {

    /**
     * {@link Config}
     */
    @Getter
    private final Config config;

    public Auth2Utils(Config config) {
        this.config = config;
    }

    /**
     * access_token过期时间
     */
    private long expiredTime;

    /**
     * 缓存的access_token
     */
    private String accessToken;

    /**
     * 使用 Token 初始化账号Client
     * @return Client
     * @throws Exception 请求异常
     */
    public static Client createClient() throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.protocol = "https";
        config.regionId = "central";
        return new Client(config);
    }

    /**
     * 获取token
     * @link 钉钉文档链接 -> <a href="https://open.dingtalk.com/document/orgapp-server/obtain-the-access_token-of-an-internal-app">获取企业内部应用的accessToken</a>
     * @apiNote 新版Api
     * @return access_token
     * @throws TeaException 含有 code 和 message 属性，可帮助开发定位问题
     */
    public synchronized String getAccessToken() {
        //如果缓存中没有数据获取该access_token已过期
        if ( accessToken == null || expiredTime <= System.currentTimeMillis() ) {
            try {
                Client client = createClient();
                GetAccessTokenRequest request = new GetAccessTokenRequest();
                request.setAppKey(config.getAppKey());
                request.setAppSecret(config.getAppSecret());
                GetAccessTokenResponseBody body = client.getAccessToken(request).getBody();
                expiredTime = System.currentTimeMillis() + body.getExpireIn();
                accessToken = body.getAccessToken();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return accessToken;
    }

//    /**
//     * 通过免登码获取用户信息
//     * @link <a href="https://open.dingtalk.com/document/orgapp-server/enterprise-internal-application-logon-free">企业内部应用免登</a>
//     * @param requestAuthCode 请求授权码
//     * @return 返回用户编号
//     */
//    public static String getUserId(String requestAuthCode) {
//        // 获取access_token，注意正式代码要有异常流处理
//        String access_token= getAccessToken();
//        // 获取用户信息
//        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
//        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
//        request.setCode(requestAuthCode);
//        request.setHttpMethod("GET");
//        OapiUserGetuserinfoResponse response = ExUtils.ignore(() -> client.execute(request, access_token));
//        //检查是否请求异常，异常则抛出业务消息
//        if ( !response.isSuccess() )
//            log.error("通过免登码获取用户信息失败：" + response.getBody());
//        // 查询得到当前用户的userId
//        // 获得到userId之后应用应该处理应用自身的登录会话管理（session）,避免后续的业务交互（前端到应用服务端）每次都要重新获取用户身份，提升用户体验
//        return response.getUserid();
//    }
//
    /**
     * 查询用户详情
     * @param userId 用户编号
     * @return 返回用户详情
     */
    public Object getUser(String userId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setUserid(userId);
        req.setLanguage("zh_CN");
        OapiV2UserGetResponse rsp = TryCatch.of(() -> client.execute(req, getAccessToken())).orElseThrow();
        if ( !rsp.isSuccess() )
            log.error("查询用户详情失败：" + rsp.getBody());
        return rsp.getResult();
    }
//
//    public static Object getUserByUnionId(String unionId) {
//        return getUser(getUserIdByUnionId(unionId));
//    }
//
//    /**
//     * 根据unionId获取用户userid
//     * @param unionId 钉钉unionId
//     * @return 返回userid
//     */
//    public static String getUserIdByUnionId(String unionId) {
//        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
//        OapiUserGetbyunionidRequest req = new OapiUserGetbyunionidRequest();
//        req.setUnionid(unionId);
//        OapiUserGetbyunionidResponse rsp = ExUtils.ignore(() -> client.execute(req, getAccessToken()));
//        if ( !rsp.isSuccess() )
//            log.error("根据unionId获取用户userid失败：" + rsp.getBody());
//        return rsp.getResult().getUserid();
//    }


}
